/**
 * 
 */
package edu.umd.clip.jobs;

import java.util.concurrent.locks.*;
import java.util.*;
/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
public class JobGroup {
	private String name;
	private ReentrantLock lock;
	private Condition done;
	private HashSet<Job> jobs;
	
	/**
	 * @param name
	 */
	protected JobGroup(String name) {
		this.name = name;
		lock = new ReentrantLock();
		done = lock.newCondition();
		jobs = new HashSet<Job>();
	}

	protected void addJob(Job job) {
		try {
			lock.lock();
			job.setGroup(this);
			jobs.add(job);
			//System.out.println("GRP "+name+": Added job '"+job.getName()+"'");
		} finally {
			lock.unlock();
		}
	}
	
	protected void jobFinished(Job job) {
		try {
			lock.lock();
			jobs.remove(job);
			//System.out.println("GRP "+name+": Removed job '"+job.getName()+"'");
			if (jobs.isEmpty()) {
				done.signalAll();
			}
		} finally {
			lock.unlock();
		}
	}
	
	public void join() {
		this.join(0);
	}
	
	public void join(int maxJobs) {
		JobManager manager = JobManager.getInstance();
		try {
			lock.lock();
			while(jobs.size() > maxJobs) {
				manager.goingToBlock();
				done.await();
				manager.goingToUnBlock();
			}
			//System.out.println("Group '"+name+"' is empty.");
		} catch(InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return name;
	}
	
}
